package com.yugao.fintech.draper.admin.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.amazonaws.services.s3.model.S3Object;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yugao.fintech.draper.admin.convert.FileConvert;
import com.yugao.fintech.draper.admin.entity.FileInfo;
import com.yugao.fintech.draper.admin.manager.OssManager;
import com.yugao.fintech.draper.admin.mapper.FileMapper;
import com.yugao.fintech.draper.admin.param.FileInfoVO;
import com.yugao.fintech.draper.admin.param.FileQuery;
import com.yugao.fintech.draper.admin.service.FileService;
import com.yugao.fintech.draper.oss.propertie.FileStorageProperties;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
@Service
public class FileServiceImpl implements FileService {
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private OssManager ossManager;
    @Autowired
    private FileStorageProperties ossProperties;

    /**
     * 上传文件
     */
    @Override
    public Dict uploadFile(MultipartFile file) {
        String fileName = LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE)
                + StrUtil.SLASH + IdUtil.simpleUUID()
                + StrUtil.DOT
                + FileUtil.extName(file.getOriginalFilename());
        String bucketName = ossProperties.getOss().getBucketName();
        Dict res = Dict.create();
        res.put("bucketName", bucketName);
        res.put("fileName", fileName);
        res.put("url", String.format("/admin/oss/%s/%s", bucketName, fileName));
        File tempFile = FileUtil.createTempFile(FileUtil.getTmpDir());
        try {
            file.transferTo(tempFile);
            String location = ossManager.partUpload(bucketName, fileName, tempFile, file.getContentType());
            res.put("location", location);
            log.info("分片上传完成:{}", location);
            // 记录到数据库
            fileLog(file, fileName);
        } catch (Exception e) {
            log.error("上传失败", e);
            return null;
        } finally {
            FileUtil.del(tempFile);
        }
        return res;
    }

    /**
     * 文件管理数据记录 收集管理追踪文件
     *
     * @param file     上传文件格式
     * @param fileName 文件名
     */
    private void fileLog(MultipartFile file, String fileName) {
        FileInfo fileInfo = FileInfo.builder()
                .fileName(fileName)
                .original(file.getOriginalFilename())
                .fileSize(file.getSize())
                .type(FileUtil.extName(file.getOriginalFilename()))
                .bucketName(ossProperties.getOss().getBucketName())
                .build();
        fileMapper.insert(fileInfo);
    }

    /**
     * 修改
     */
    @Override
    public Boolean updateFile(FileInfoVO fileInfoVO) {
        return fileMapper.updateById(FileConvert.INSTANCE.convert(fileInfoVO)) > 0;
    }

    /**
     * 分页
     */
    @Override
    public IPage<FileInfoVO> pageQuery(FileQuery fileQuery) {
        Page<FileInfo> pageInfo = fileMapper.selectPage(Page.of(fileQuery.getPageNum(), fileQuery.getPageSize()), Wrappers.emptyWrapper());
        return FileConvert.INSTANCE.convert(pageInfo);
    }

    /**
     * 获取单条
     */
    @Override
    public FileInfoVO findById(Long id) {
        return FileConvert.INSTANCE.convert(fileMapper.selectById(id));
    }

    /**
     * 获取全部
     */
    @Override
    public List<FileInfoVO> findAll() {
        return FileConvert.INSTANCE.convert(fileMapper.selectList(Wrappers.emptyWrapper()));
    }

    /**
     * 删除文件
     */
    @SneakyThrows
    @Override
    public Boolean deleteFile(Long id) {
        FileInfo fileInfo = fileMapper.selectById(id);
        ossManager.removeObject(fileInfo.getBucketName(), fileInfo.getFileName());
        return fileMapper.deleteById(id) > 0;
    }

    /**
     * 下载文件
     *
     * @param bucket   桶名称
     * @param fileName 文件名
     * @param response 响应
     */
    @Override
    public void getFile(String bucket, String fileName, HttpServletResponse response) {
        try (S3Object s3Object = ossManager.getObject(bucket, fileName)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            IoUtil.copy(s3Object.getObjectContent(), response.getOutputStream());
        } catch (Exception e) {
            log.error("文件读取异常: {}", e.getLocalizedMessage());
        }
    }
}